/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package deatax.display;

import deatax.GameData;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.media.opengl.GL2;
import javax.media.opengl.glu.GLU;

/**
 *
 * @author Caroline
 */
public class Camera implements MouseMotionListener, MouseListener, MouseWheelListener, TweenListener {

    Tween tweener;
    
    //float[] pos;
    float[] lookat;
    double height = 20;
    boolean project = true;
    GameData data;
    float[] ray = new float[6];
    Point last_point;

    public Camera(GameData data) {
        //pos = new float[]{0, 20, 0};
        
        tweener = new Tween(0, 20, 0);
        lookat = new float[]{0, -50, 0};
        this.data = data;
        data.getDisplay().addMouseMotionListener(this);
        data.getDisplay().addMouseListener(this);
        data.getDisplay().addMouseWheelListener(this);
    }

    public void setTarget(float[] pos) {
        tweener.setTarget(pos);
    }
    
    
    public void setProjection(GL2 gl) {
        GLU glu = new GLU();
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();

        
//        System.out.println(tweener);
        tweener.step();
//        System.out.println(tweener);
        
        //double height = data.getDisplay().getWidth() / 20f;
        glu.gluLookAt(tweener.current.x, tweener.current.y, tweener.current.z + height, tweener.current.x + lookat[0], tweener.current.y + lookat[1], 0, 0, -1, 0);
        //System.out.println(pos[0] + ", " + pos[1] + ", " + pos[2]);


        if (project) {
            Point mouse = MouseInfo.getPointerInfo().getLocation();
            Point window = data.getDisplay().getLocationOnScreen();


            float[] fbuffer = new float[32];
            gl.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, fbuffer, 0);
            gl.glGetFloatv(GL2.GL_PROJECTION_MATRIX, fbuffer, 16);

            int[] ibuffer = new int[4];
            gl.glGetIntegerv(GL2.GL_VIEWPORT, ibuffer, 0);

            int x = mouse.x - window.x;
//            System.out.println(window.y);
            int y = ibuffer[3] - mouse.y + window.y;

            glu.gluUnProject(x, y, 0, fbuffer, 0, fbuffer, 16, ibuffer, 0, ray, 0);
            glu.gluUnProject(x, y, 1f, fbuffer, 0, fbuffer, 16, ibuffer, 0, ray, 3);



            float[] ray_vector = new float[6];

            float t = 0;
            //Calculate the initial vector
            for (int i = 0; i < 3; i++) {
                ray_vector[i] = ray[i];
                ray_vector[i + 3] = ray[i] - ray[i + 3];
                t += Math.abs(ray_vector[i + 3]);
            }
            //unit the direction component
            for (int i = 3; i < 6; i++) {
                ray_vector[i] = ray_vector[i] / t;
            }
            t = (ray_vector[2] / ray_vector[5]);
            ray[3] = ray_vector[0] - ray_vector[3] * t;
            ray[4] = ray_vector[1] - ray_vector[4] * t;
            ray[5] = 0;

            data.getRender().cursor.setLocation(ray[3], ray[4]);

        }

        gl.glBegin(GL2.GL_LINES);
        gl.glVertex3fv(ray, 0);
        gl.glVertex3fv(ray, 3);
        gl.glEnd();
    }

    public void mouseDragged(MouseEvent e) {

        if (tweener.testFinished()) {
            if (last_point != null) {
                //
                //            if (e.isAltDown()) {
                //                lookat[0] -= (last_point.x - e.getX()) / 8f;
                //                lookat[1] += (last_point.y - e.getY()) / 8f;
                //            } else {
                tweener.forceAddPos( - (last_point.x - e.getX()) / 8f, (last_point.y - e.getY()) / 8f, 0);
                //pos[1] += ;
                //            }
            }
            last_point = e.getPoint();
        }
    }

    @Override
    public String toString() {
        //return "Camera[pos:(" + pos[0] + "," + pos[1] + "," + pos[2] + "), lookat:(" + lookat[0] + "," + lookat[1] + "," + lookat[2] + ")]";
        return "GOTO: hell";
    }

    public void mouseMoved(MouseEvent e) {
    }

    public void mouseClicked(MouseEvent e) {
        if (tweener.testFinished()) {
            project = true;
        }
    }

    public void mousePressed(MouseEvent e) {
        if (tweener.testFinished()) {
            last_point = e.getPoint();
        }
    }

    public void mouseReleased(MouseEvent e) {
        if (tweener.testFinished()) {
            last_point = null;
        }
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
        if (tweener.testFinished()) {
            last_point = null;
        }
    }

    public void mouseWheelMoved(MouseWheelEvent e) {
        if (tweener.testFinished()) {
            int r = e.getWheelRotation();
            double npos = tweener.current.z + r;
            //System.out.println(npos);
            if (npos > 50 || npos < -10) {
                return;
            }
            tweener.forceAddPos(0, 0, e.getWheelRotation());
        }
    }

    @Override
    public void onTweenFinished(Tween t) {
        
    }
}
